import { CCClass, Component } from "cc";
import { FuiCom } from "../../ui_gen/FuiCom";
import { CMD } from "./BaseCMD";
import { CCCtrl, FuiCtrl, UICtrl } from "./BaseCtrl";
import { BaseFacade } from "./BaseFacade";
import { BaseModel } from "./BaseModel";
import { GameMediator } from "./GameMediator";
import { puremvc } from "./puremvc";
export class RegistPMVC {
    static funcs: { order: number, func: Function }[] = [];
    static isExecuted = false;
    static registFunc(order: number, func: Function) {
        this.funcs.push({ order: order, func: func });
        this.funcs.sort((a, b) => {
            return a.order - b.order;
        });
    }
    static registView<T extends Component, K extends BaseFacade>(comCtor: Ctor<T>, facade: Ctor<K>, mediator: GameMediator) {
        this.viewComMap.set(comCtor, new CCCtrl(comCtor, facade, mediator));
    }
    static registFView<T extends FuiCom, K extends BaseFacade>(comCtor: Ctor<T>, facade: Ctor<K>, mediator: GameMediator) {
        this.viewComMap.set(comCtor, new FuiCtrl(comCtor, facade, mediator));
    }
    static excuteFunc() {
        for (let i = 0; i < this.funcs.length; i++) {
            this.funcs[i].func();
        }
        this.isExecuted = true;
    }
    static bindView<T>(ctor: Ctor<T>, com: T) {
        let bind = () => {
            if (!this.viewComMap.has(ctor)) {
                console.error(`没有找到${ctor.name}的facade和mediator，请检查装饰器`);
                return;
            }
            let ctrl = this.viewComMap.get(ctor);
            ctrl.bind(com);
        }
        if (!this.isExecuted) {
            this.registFunc(5, bind);
        }
        else {
            bind();
        }
    }
    static unbindView<T>(ctor: Ctor<T>) {
        let bind = () => {
            if (!this.viewComMap.has(ctor)) {
                console.error(`没有找到${ctor.name}的facade和mediator，请检查装饰器`);
                return;
            }
            let { facade, mediator } = this.viewComMap.get(ctor);
            let med = puremvc.Facade.getInstance(facade).retrieveMediator(mediator) as GameMediator;
            med.viewComponent = null;
            this.viewComMap.delete(ctor);

        }
        if (!this.isExecuted) {
            this.registFunc(5, bind);
        }
        else {
            bind();
        }
    }
    static getViewPackage(ctor: Ctor<any>) {
        return this.viewComMap.get(ctor);
    }
    static viewComMap: Map<Ctor<any>, UICtrl<any>> = new Map();
}
export type Ctor<T> = new (...args: any[]) => T
export function RFacade<T extends BaseFacade>() {
    return function (facade: Ctor<T>) {
        let func = function () {
            new facade(facade.name);
        }
        CCClass({ name: facade.name, ctor: facade, extends: BaseFacade });
        RegistPMVC.registFunc(-1, func);

    }
}
export function RCommand<K extends BaseFacade, T extends CMD<any>>(facade: Ctor<K>) {
    return function (cmd: Ctor<T>) {
        let func = function () {
            (puremvc.Facade.getInstance(facade.name) as puremvc.Facade).registerCommand(cmd.name, cmd);
        }
        RegistPMVC.registFunc(2, func);

    }
}
export function RMediator<K extends BaseFacade, T extends GameMediator>(facade: Ctor<K>) {
    return function (mediator: Ctor<T>) {
        let func = function () {
            (puremvc.Facade.getInstance(facade.name) as BaseFacade).registerMediator(new mediator(mediator.name, null));
        }
        RegistPMVC.registFunc(1, func);
    }
}
export function RModel<K extends BaseFacade, T extends BaseModel>(facade: Ctor<K>) {
    return function (model: Ctor<T>) {
        let func = function () {
            (puremvc.Facade.getInstance(facade.name) as puremvc.Facade).registerProxy(new model(model.name));
        }
        RegistPMVC.registFunc(0, func);
    }
}
export function RCtrl<K extends BaseFacade, T extends Component>(facade: Ctor<K>) {
    return function (ctrl: Ctor<T>) {
        let func = function () {
            let mediator = new GameMediator();
            (puremvc.Facade.getInstance(facade.name) as BaseFacade).registerMediator(mediator);
            RegistPMVC.registView(ctrl, facade, mediator);
        }
        RegistPMVC.registFunc(1, func);
    }
}
export function RFCtrl<K extends BaseFacade, T extends FuiCom>(facade: Ctor<K>) {
    return function (ctrl: Ctor<T>) {
        let func = function () {
            let mediator = new GameMediator();
            (puremvc.Facade.getInstance(facade.name) as BaseFacade).registerMediator(mediator);
            RegistPMVC.registFView(ctrl, facade, mediator);
        }
        RegistPMVC.registFunc(1, func);
    }
}